 package br.com.async.infrastructure.impl;

import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;

import br.com.async.domain.reserve.Reserve;
import br.com.async.domain.reserve.ReserveRepository;
import br.com.async.domain.reserve.Shift;
import br.com.async.domain.reserve.Time;
import br.com.async.infrastructure.AbstractRepositoryImpl;
import br.com.async.util.ResponseData;

public class ReserveRepositoryImpl extends
		AbstractRepositoryImpl<Reserve, Integer> implements ReserveRepository {

	public ReserveRepositoryImpl() {
		super(Reserve.class);
	}

	public Reserve findUniqueReserveByCriterions(Integer roomCode,
			Calendar date, Shift shift) {
		Criteria criteria = getSession().createCriteria(entityClass);

		criteria.createAlias("room", "r");
		criteria.add(Restrictions.eq("r.code", roomCode));

		criteria.add(Restrictions.eq("date", date));
		criteria.add(Restrictions.eq("shift", shift));

		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		return (Reserve) criteria.uniqueResult();
	}

	public List<Reserve> findReserveByCriterions(Integer roomCode,
			Calendar date, Shift shift) {
		Criteria criteria = getSession().createCriteria(entityClass);

		criteria.createAlias("room", "r");
		criteria.add(Restrictions.eq("r.code", roomCode));

		criteria.add(Restrictions.eq("date", date));
		criteria.add(Restrictions.eq("shift", shift));

		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		return (List<Reserve>) criteria.list();
	}

	public List<Reserve> findReserveByCriterions(String roomName,
			Calendar date, Shift shift) {
		Criteria criteria = getSession().createCriteria(entityClass);

		criteria.createAlias("room", "r");

		if (roomName != null)
			criteria.add(Restrictions.ilike("r.name", roomName,
					MatchMode.ANYWHERE));
		else
			criteria.add(Restrictions.ilike("r.name", "", MatchMode.ANYWHERE));

		if (date != null)
			criteria.add(Restrictions.eq("date", date));
		else
			criteria.add(Restrictions.eq("date", Calendar.getInstance()));

		if (shift != null)
			criteria.add(Restrictions.eq("shift", shift));

		Set set = new HashSet(criteria.list());

		return (List<Reserve>) criteria.list();

	}

	/**
	 * @param search
	 * @param offset
	 * @param maxResult
	 * @return
	 */
	public ResponseData<Reserve> listReserveByCriterions(String search,
			Integer offset, Integer maxResult) {

		ResponseData<Reserve> rd = new ResponseData<Reserve>();
		Criteria criteria = getSession().createCriteria(entityClass);
		criteria.createAlias("attendant", "at");
		criteria.createAlias("at.person", "atp");

		criteria.createAlias("responsible", "res");
		criteria.createAlias("res.person", "resp");

		if (!search.trim().isEmpty() || search != null) {

			Criterion c1 = Restrictions.ilike("atp.name", search,
					MatchMode.ANYWHERE);
			Criterion c2 = Restrictions.ilike("resp.name", search,
					MatchMode.ANYWHERE);
			criteria.add(Restrictions.or(c1, c2));

		}

		return null;
	}

	@Override
	public List<Reserve> findReserveForRomAndDate(String room, Calendar date) {
		Criteria criteria = getSession().createCriteria(entityClass);
		criteria.createAlias("room", "r");

		Criterion c1 = Restrictions.eq("date", date);
		Criterion c2 = Restrictions.eq("r.number", room);

		criteria.add(Restrictions.and(c1, c2));

		return criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
				.list();
	}

	@Override
	public List<Time> findTimeFreeFromReserve(Reserve reserve) {
		Criteria criteria = getSession().createCriteria(entityClass);

		Criterion c1 = Restrictions.eq("times", reserve.getTimes());

		criteria.add(c1);
		return criteria.list();
	}

	public List<Reserve> findReserveByResponsible(Integer respCode) {
		
		Criteria criteria = getSession().createCriteria(entityClass);
		
		criteria.createAlias("personResponsible","r");
			
		criteria.add(Restrictions.eq("r.code", respCode));

		return criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
				.list();
	}
	
	public List<Reserve> findReserveByCriterions(
			Calendar date) {
		Criteria criteria = getSession().createCriteria(entityClass);

		criteria.add(Restrictions.eq("date", date));

		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		return (List<Reserve>) criteria.list();
	}
	

	public List<Reserve> findReserveByCriterions(Integer respCode, Calendar date) {
		Criteria criteria = getSession().createCriteria(entityClass);

		criteria.createAlias("personResponsible","r");
		
		Criterion c1 = Restrictions.eq("r.code", respCode);
		
		Criterion c2 = Restrictions.eq("date", date);
		
		criteria.add(Restrictions.and(c1, c2));
		
		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		return (List<Reserve>) criteria.list();
	}
	
}
